//
//
//  Created by 乐启榜 on 16/8/5.
//  Copyright © 2016年 乐启榜. All rights reserved.
//



import UIKit

public enum QBPageMenuOptions {
    
    case MeunViewHeight(CGFloat)
    case MenuViewBackgroundColor(UIColor)
    
    case MenuItemFont(UIFont)
    case MenuItemNormalColor(UIColor)
    case MenuItemSpace(CGFloat)
    case MenuItemDefaultIndex(Int)
    
    case MenuIsSelectionIndicator(Bool)
    case MenuSelectionIndicatorColor(UIColor)
    case MenuSelectionIndicatorHeight(CGFloat)
    
    case MenuIsRightButton(Bool)
    case MenuRightButtonWidth(CGFloat)
    case MenuRightButtonBackgroundColor(UIColor)
    
    case AnimationDuration(NSTimeInterval)
}

class QBMenuMainController: UIViewController,UIScrollViewDelegate {
    
    var controllersArray: [UIViewController] = []        // controller数组
    var scrollAnimationDurationBaseOnMenuItemTap: Int = 500
    
    var menuViewHeight: CGFloat = 44.0
    var menuViewBackgroundColor: UIColor = UIColor.whiteColor()
    
    var menuIsSelectionIndicator: Bool = true
    var menuselectionIndicatorColor: UIColor = UIColor.redColor()
    var menuselectionIndicatorHeight: CGFloat = 3.0
    
    var menuIsRightButton: Bool = true
    var menuRightButtonWidth: CGFloat = 30.0
    var menuRightButtonBackgroundColor: UIColor = UIColor.whiteColor()
    
    var menuItemSpace: CGFloat = 7.0
    var menuItemNormalColor: UIColor = UIColor.lightGrayColor()
    var menuItemFont: UIFont = UIFont.systemFontOfSize(19.0)
    var menuItemDefaultIndex: Int = 0
    
    var animationDuration: NSTimeInterval = 0.2
    
    
    private var menuMainView: QBMenuMainView!
    private var controllerScrollView: UIScrollView!
    
    private var controllerCount: Int = 0    // 控制器数量
    private var didTapMenuItemScroll: Bool = false // 用于判断手势点击触发还是滑动触发
    private var didScrollAlready: Bool = false // 用于判断是否滚动
    
    private var lastControllerScrollViewContentOffset: CGFloat  = 0.0
    private var startingPageForScroll: Int = 0 // 保存当前下标，用于计算scroll的偏移量判断切换的方向
    private var lastScrollDirection: QBPageMenuScrollViewDirection = .Other// 方向
    
    private var currentPageIndex: Int = 0 // 用于保存当前显示页面的下标
    private var lastPageIndex: Int = 0 // 上一个下标
    private var pageAddedDictionary: [Int : Int] = [:]// 保存已经添加控制器的下标
    
    private var tapTimer: NSTimer?//
    
    private var currentOrientationIsPortrait: Bool = true
    private var didLayoutSubviewsAfterRotation: Bool = false
    
    enum QBPageMenuScrollViewDirection: Int {
        case Left
        case Right
        case Other
    }
    
    internal init(viewControllers: [UIViewController],frame: CGRect, options: [String: AnyObject]?){
        super.init(nibName: nil, bundle: nil)
        
        controllersArray = viewControllers
        controllerCount = viewControllers.count
        
        self.view.frame = frame
    }
    
    internal convenience init(viewControllers: [UIViewController], frame: CGRect, pageMenuOptions: [QBPageMenuOptions]?){
        self.init(viewControllers:viewControllers, frame:frame, options:nil)
        
        guard let _options = pageMenuOptions else {return}
        for _option in _options {
            switch _option {
                
            case let .MeunViewHeight(value):
                menuViewHeight = value
            case let .MenuViewBackgroundColor(value):
                menuViewBackgroundColor = value
                
            case let .MenuItemFont(value):
                menuItemFont = value
            case let .MenuItemNormalColor(value):
                menuItemNormalColor = value
            case let .MenuItemSpace(value):
                menuItemSpace = value
            case let .MenuItemDefaultIndex(value):
                menuItemDefaultIndex = value
                
            case let .MenuIsSelectionIndicator(value):
                menuIsSelectionIndicator = value
            case let .MenuSelectionIndicatorColor(value):
                menuselectionIndicatorColor = value
            case let .MenuSelectionIndicatorHeight(value):
                menuselectionIndicatorHeight = value
                
            case let .MenuIsRightButton(value):
                menuIsRightButton = value
            case let .MenuRightButtonWidth(value):
                menuRightButtonWidth = value
            case let .MenuRightButtonBackgroundColor(value):
                menuRightButtonBackgroundColor = value
                
            case let .AnimationDuration(value):
                animationDuration = value
                
            }
        }
        
        setUpUserInterface()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    private func setUpUserInterface() {
        
        let options: [QBMenuViewOptions]
            = [.menuHeigth(menuViewHeight),
               .menuBackgroundColor(menuViewBackgroundColor),
               
               .menuItemNormalColor(menuItemNormalColor),
               .menuItemSpace(menuItemSpace),
               .menuItemFont(menuItemFont),
               .menuItemDefaultIndex(menuItemDefaultIndex),
          
               .isSelectionIndicator(menuIsSelectionIndicator),
               .selectionIndicatorColor(menuselectionIndicatorColor),
               .selectionIndicatorHeight(menuselectionIndicatorHeight),
               
               .isRightButton(menuIsRightButton),
               .rightButtonBackgroundColor(menuRightButtonBackgroundColor),
               .rightButtonWidth(menuRightButtonWidth),
               
               .animationDuration(animationDuration)]
        
        menuMainView
            = QBMenuMainView(frame: CGRect(x: 0, y: 20, width: self.view.frame.width, height: menuViewHeight),
                             options: options)
        menuMainView.dataSource = self
        menuMainView.delegate = self
        self.view.addSubview(menuMainView)
        
        controllerScrollView = UIScrollView(frame: CGRect(x: 0.0, y: menuViewHeight + 20, width: self.view.frame.width, height: self.view.frame.height - menuViewHeight - 20))
        controllerScrollView.backgroundColor = UIColor.grayColor()
        view.addSubview(controllerScrollView)
        controllerScrollView.delegate = self
        controllerScrollView.pagingEnabled = true
        controllerScrollView.bounces = false
        controllerScrollView.showsVerticalScrollIndicator = false
        controllerScrollView.showsHorizontalScrollIndicator = false
        controllerScrollView.contentSize = CGSize(width: self.view.frame.width * CGFloat(controllerCount), height: 0)
        
        addPageAtIndex(menuItemDefaultIndex)
    }
    
    
    func scrollViewDidScroll(scrollView: UIScrollView) {
        
        if !didLayoutSubviewsAfterRotation {
    
            if scrollView.isEqual(controllerScrollView){
                
                if scrollView.contentOffset.x >= 0 && scrollView.contentOffset.x <= (CGFloat(controllerCount - 1) * self.view.frame.width) {
                    
                    if (currentOrientationIsPortrait && UIApplication.sharedApplication().statusBarOrientation.isPortrait) || (!currentOrientationIsPortrait && UIApplication.sharedApplication().statusBarOrientation.isLandscape) {
                        
                        if !didTapMenuItemScroll {
                            // 判断是第一滚动
                            if didScrollAlready {
                                var newScrollDirection: QBPageMenuScrollViewDirection = .Other
                                // 判断滑动方向
                                if (CGFloat(startingPageForScroll) * scrollView.frame.width > scrollView.contentOffset.x){
                                    newScrollDirection = .Right
                                }else if(CGFloat(startingPageForScroll) * scrollView.frame.width < scrollView.contentOffset.x) {
                                    newScrollDirection = .Left
                                }
                                
                                if newScrollDirection != .Other && lastScrollDirection != newScrollDirection{
                                    let index: Int = newScrollDirection == .Left ? currentPageIndex + 1 : currentPageIndex - 1
                                    if index >= 0 && index < controllerCount{
                                        
                                        if pageAddedDictionary[index] != index {
                                            addPageAtIndex(index)// 添加视图
                                            pageAddedDictionary[index] = index// 保存下标
                                            
                                        }
                                    }
                                }
                                
                                lastScrollDirection = newScrollDirection
                            }
                            // 判断不是第一次滚动，当第一次运行程序时，只默认为falsh，走这里
                            if !didScrollAlready {
                                // 最后一scrollView的偏移量与当前scrollView的偏移量大小，判定滑动的方向
                                // 先左滑动
                                if lastControllerScrollViewContentOffset > scrollView.contentOffset.x {
                                    
                                    if currentPageIndex != controllerCount - 1{
                                        let index: Int = currentPageIndex - 1
                                        if pageAddedDictionary[index] != index && index >= 0 && index < controllerCount - 1 {
                                            addPageAtIndex(index)
                                            pageAddedDictionary[index] = index
                                        }
                                        lastScrollDirection = .Right // 保存方向
                                    }
                                    
                                    // 向右滑动
                                }else if lastControllerScrollViewContentOffset <= scrollView.contentOffset.x {
                                    
                                    if currentPageIndex != 0 {
                                        let index: Int = currentPageIndex + 1
                                        if pageAddedDictionary[index] != index && index >= 0 && index < controllerCount{
                                            addPageAtIndex(index)
                                            pageAddedDictionary[index] = index
                                        }
                                        lastScrollDirection = .Left
                                    }
                                    
                                    // 如果都不是则为程序第一次启动，这是didScrollAlready为true
                                }
                                didScrollAlready = true
                            }
                            lastControllerScrollViewContentOffset = scrollView.contentOffset.x
                        }
                        
                        let width: CGFloat = controllerScrollView.frame.width
                        let page: Int = Int(controllerScrollView.contentOffset.x / width)
                        if page != currentPageIndex {
                            lastPageIndex = currentPageIndex
                            currentPageIndex = page
                            
                            if pageAddedDictionary[page] != page && page < controllerCount && page >= 0 {
                                addPageAtIndex(page)
                                pageAddedDictionary[page] = page
                            }
                            
                            if !didTapMenuItemScroll {
                                if pageAddedDictionary[lastPageIndex] != lastPageIndex {
                                    pageAddedDictionary[lastPageIndex] = lastPageIndex
                                }
                                
                                let indexLeftTwo : Int = page - 2
                                if pageAddedDictionary[indexLeftTwo] == indexLeftTwo {
                                    pageAddedDictionary.removeValueForKey(indexLeftTwo)
                                    removePageAtIndex(indexLeftTwo)
                                }
                                let indexRightTwo : Int = page + 2
                                if pageAddedDictionary[indexRightTwo] == indexRightTwo {
                                    pageAddedDictionary.removeValueForKey(indexRightTwo)
                                    removePageAtIndex(indexRightTwo)
                                }
                            }
                        }
                        
                        menuMainView.pageContentOffsetX = scrollView.contentOffset.x //同步到menuMainView做标题跟随page滑动
                    }
                }else{

                }
            }
        }else if didLayoutSubviewsAfterRotation == true{
            
            didLayoutSubviewsAfterRotation = false
            
//            if scrollView.isEqual(controllerScrollView){
            
                menuMainView.pageContentOffsetX = scrollView.contentOffset.x //同步到menuMainView做标题跟随page滑动
//            }
        }
    }
    
    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        if scrollView.isEqual(controllerScrollView) {
            
            for key in pageAddedDictionary.keys {
                if key != currentPageIndex {
                    removePageAtIndex(key)
                    pageAddedDictionary.removeValueForKey(key)
                }
            }
            didScrollAlready = false
            startingPageForScroll = currentPageIndex
            pageAddedDictionary.removeAll(keepCapacity: false)
        }
    }
    
    func scrollViewDidEndTapScrollViewAnimation(){
        
        for key in pageAddedDictionary.keys {
            if key != currentPageIndex {
                removePageAtIndex(key)
                pageAddedDictionary.removeValueForKey(key)
            }
        }
        
        startingPageForScroll = currentPageIndex
        didTapMenuItemScroll = false
        pageAddedDictionary.removeAll(keepCapacity: false)
        
    }
    
    private func handleViewSeletedIndex(itemIndex: Int){
        
        guard itemIndex >= 0 && itemIndex < controllerCount else {return}
        
        if itemIndex != currentPageIndex {
            startingPageForScroll = itemIndex
            lastPageIndex = currentPageIndex
            
            currentPageIndex = itemIndex
            didTapMenuItemScroll = true
            
            // 如果不是相邻按钮的点击事件
            let smallerIndex: Int = lastPageIndex < currentPageIndex ? lastPageIndex : currentPageIndex
            let lagerIndex: Int   = lastPageIndex > currentPageIndex ? lastPageIndex : currentPageIndex
            
            if smallerIndex + 1 != lagerIndex {
                for index in (smallerIndex + 1)...(lagerIndex - 1) {
                    if pageAddedDictionary[index] != index {
                        addPageAtIndex(index)
                        pageAddedDictionary[index] = index
                    }
                }
            }
            // 如果不是相邻按钮的点击事件 截止
            addPageAtIndex(itemIndex)
            pageAddedDictionary[lastPageIndex] = lastPageIndex
            
            //*******动画效果***************
            weak var weakSelf = self
            guard let _weakSelf = weakSelf else{return}
            
            let duration: Double = Double(scrollAnimationDurationBaseOnMenuItemTap) / Double(1000)
            
            let offsetX: CGFloat = CGFloat(itemIndex) * self.controllerScrollView.frame.width
            
            UIView.animateWithDuration(duration, animations: { 
                _weakSelf.controllerScrollView.contentOffset = CGPoint(x: offsetX, y: _weakSelf.controllerScrollView.contentOffset.y)
            })
            
            if tapTimer != nil{
                tapTimer?.invalidate()
            }
            
            let timerInterval: NSTimeInterval = Double(scrollAnimationDurationBaseOnMenuItemTap) * 0.001
            tapTimer = NSTimer.scheduledTimerWithTimeInterval(timerInterval, target: self, selector: #selector(scrollViewDidEndTapScrollViewAnimation), userInfo: nil, repeats: true)
            
            //*******动画效果 截止***************
            
        }
    }
    
    private func addPageAtIndex(index: Int){
        let newVC = controllersArray[index]
        newVC.willMoveToParentViewController(self)
        newVC.view.frame = CGRect(x: self.view.frame.width * CGFloat(index), y:0, width: self.view.frame.width, height: self.view.frame.height)
        
        self.addChildViewController(newVC)
        self.controllerScrollView.addSubview(newVC.view)
        newVC.didMoveToParentViewController(self)
        
    }
    private func removePageAtIndex(index: Int){
        let oldVC = controllersArray[index]
        
        oldVC.willMoveToParentViewController(nil)
        oldVC.view.removeFromSuperview()
        oldVC.removeFromParentViewController()
    }
    
    override func viewDidLayoutSubviews() {

        controllerScrollView.contentSize = CGSize(width: CGFloat(controllerCount) * self.view.frame.width, height: self.view.frame.height - menuViewHeight)
        
        let oldOrientationIsPortrait: Bool = currentOrientationIsPortrait
        currentOrientationIsPortrait = UIApplication.sharedApplication().statusBarOrientation.isPortrait
        
        if (oldOrientationIsPortrait && UIDevice.currentDevice().orientation.isLandscape) || (!oldOrientationIsPortrait && UIDevice.currentDevice().orientation.isPortrait){
            
            didLayoutSubviewsAfterRotation = true
            
            if UIDevice.currentDevice().orientation.isPortrait {
                
                menuMainView.frame = CGRect(x: 0, y: 20, width: self.view.frame.width, height: menuViewHeight)
                
            }else if UIDevice.currentDevice().orientation.isLandscape{
                
                menuMainView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: menuViewHeight)
            }
            
            controllerScrollView.frame
                = CGRect(x: 0,
                         y: menuViewHeight + menuMainView.frame.origin.y,
                         width: self.view.frame.width,
                         height: self.view.frame.height - menuViewHeight -  menuMainView.frame.origin.y)
            
            for view in controllerScrollView.subviews {
                view.frame = CGRect(x: self.view.frame.width * CGFloat(currentPageIndex),
                                    y: 0,
                                width: self.view.frame.width,
                               height: self.view.frame.height - menuViewHeight)
            }
            
            let offset: CGFloat = CGFloat(currentPageIndex) * controllerScrollView.frame.width
            controllerScrollView.contentOffset = CGPoint(x: offset, y: 0)
        }
        
        self.view.layoutIfNeeded()
    }
}

// MARK: - QBMenuMainViewDelegate & dataSource
extension QBMenuMainController: QBMenuMainViewDelegate, QBMenuMainViewDataSource {
    
    // QBMenuMainViewDelegate
    func menuMainView(didSelectedWithIndex index: Int) {
        handleViewSeletedIndex(index)
    }
    
    // QBMenuMainViewDataSource
    func numberOfTitlesInMenu(menu: QBMenuMainView) -> Int {
        
        return controllersArray.count
    }
    
    func dropDownMenu(menu: QBMenuMainView,titleForIndex index: Int) -> String {
        let vc = controllersArray[index]
        return vc.title!
    }
}

